#!/usr/bin/python

""" CLASS/MODULE:
    Purpose:
"""
__author__ = 'liwei79@gmail.com'

POINTER_SIZE = 4
SIGNED = 1
UNSIGNED = 0

class CType:
    def __init__(self):
        assert(0)
    def setSize(self, size):
        self.size = size
    def getSize(self):
        return self.size
    def getPtrType(self):
        type = CPointerType(self)
        return type
    def getDerefType(self):
        #Sure, we can't dereference anything is not a pointer 
        assert(isinstance(self, CPointerType))
        return self.getBaseType()
    def getArrayType(self, arrSize):
        type = self.Ptr()
        type = CArrayType(type, arrSize)
        return type
    def Ptr(self):
        return self.getPtrType()
    def Deref(self):
        return self.getDerefType()
    def Arr(self, arrSize):
        return self.getArrayType(arrSize)

class CVoidType(CType):
    def __init__(self):
        ()
    def getSize(self):
        assert 0, "Can't getsize from void type"
        
class HasSign:
    def __init__(self, signed):
        self.signed = signed

class CIntegerType(CType, HasSign):
    #sign is Signed or UnSigned class
    def __init__(self, size, signed):
        CType.setSize(self, size)
        HasSign.__init__(self, signed)
    def __repr__(self):
        assert(0)

class CIntType(CIntegerType):
    def __init__(self, signed):
        CIntegerType.__init__(self, 4, signed)
    def __repr__(self):
        if self.signed:
            return "int"
        else:
            return "unsigned"

class CCharType(CIntegerType):
    def __init__(self, signed):
        CIntegerType.__init__(self, 1, signed)
    def __repr__(self):
        if self.signed:
            return "signed char"
        else:
            return "char"

class CLongType(CIntegerType):
    def __init__(self, signed):
        CIntegerType.__init__(self, 4, signed)
    def __repr__(self):
        if self.signed:
            return "long"
        else:
            return "unsigned  long"

class CLongLongType(CIntegerType):
    def __init__(self, signed):
        CIntegerType.__init__(self, 8, signed)
    def __repr__(self):
        if self.signed:
            return "long long"
        else:
            return "unsigned  long long"

class CPointerType(CType):
    def __init__(self, baseType):
        self.baseType = baseType
        self.setSize(POINTER_SIZE)
    def getBaseType(self):
        return self.baseType
    def __repr__(self):
        return repr(self.baseType) + "*"

class CArrayType(CType):
    def __init__(self, pointerType, numOfElems):
        self.setSize(0)
        self.pointerType = pointerType
        self.numOfElems = numOfElems
    def getElemType(self):
        return self.pointerType.getDerefType()
    def __repr__(self):
        return repr(self.pointerType.getBaseType()) + "[%d]" % self.numOfElems

#PREDEFINE BUILD IN TYPES
CVOID       = CVoidType()
CCHAR       = CCharType(UNSIGNED)
CSCHAR      = CCharType(SIGNED)
CINT        = CIntType(SIGNED)
CUINT       = CIntType(UNSIGNED)
CLONG       = CLongType(SIGNED)
CULONG      = CLongType(UNSIGNED)
CLONGLONG   = CLongLongType(SIGNED)
CULONGLONG  = CLongLongType(UNSIGNED)

if __name__ == "__main__":
     a = CINT.Ptr().Ptr()
     b =  CLONGLONG.Ptr().Ptr().Deref().Deref()
     c = CINT.Ptr().Arr(10)
     print a
     print a.getSize()
     print b
     print b.getSize()
     print c
     print c.getSize()
     print c.getElemType()
     print c.getElemType().getSize()
